/*
 * =====================================================================================
 *
 *       Filename:  socker.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  17.05.2012 21:52:04
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (), 
 *   Organization:  
 *
 * =====================================================================================
 */
#include "socket.hpp"

namespace Drosera {

// Empty constructor, most used
Socket::Socket ( void ) {}


// Destructor of the Socket and WSA
Socket::~Socket ( void ) {
	#ifdef WIN32
	WSACleanup();
	#endif
	closesocket ( m_sock );
}

// Init Serverdata and WSA
bool Socket::initSocket ( void ) {

	#ifdef WIN32
	WSADATA data;
	int result = WSAStartup ( MAKEWORD ( 2, 2 ), &data );
	if ( data ) return false;
	#endif
	m_sock = -1;
	return true;
}

// Creates the socket
bool Socket::createSocket ( void ) {
	
	m_sock = socket ( AF_INET, SOCK_STREAM, 0 );
	
	if ( m_sock < 0 ) return false;
	
	return true;
}

// Binds the socket
bool Socket::bindSocket ( unsigned int port ) {

	m_addr.sin_family = AF_INET;
	m_addr.sin_addr.s_addr = INADDR_ANY;
	m_addr.sin_port = htons ( port );

	int rtn = bind ( m_sock, (struct sockaddr *) &m_addr, sizeof ( m_addr ) );

	if ( rtn == -1 ) return false;

	return true;
}

// Listen on the Socket ( Server Side )
bool Socket::listenSocket ( void ) {

	int rtn = listen ( m_sock, MAXCONN );
	if ( rtn == -1 ) return false;
	
	return true;
}

// Accept a new incomming Socket ( Server Side )
SOCKET Socket::acceptSocket ( SOCKET& sock ) {

	int addr_length = sizeof ( m_addr );

	SOCKET new_s = accept ( sock , ( struct sockaddr * ) &m_addr, ( socklen_t *) &addr_length );

	if  ( new_s <= 0 ) return -1;

	return new_s;
}


// Send data throug the Socket
bool Socket::sendSocket ( std::string& data ) {
	
	int status = send ( m_sock, data.c_str(), data.size(), 0 );

	if ( status == -1) return false;

	return true;
}

// Recive data from Socket
int Socket::recvSocket ( std::string &buf ) {
	
	char data[ MAXRECV + 1 ];
	memset ( data, 0, MAXRECV + 1 );
	ssize_t size = recv ( getSocket(), data, MAXRECV, 0 );

	if ( size == 0 ) { 
		info ( "Client is disconnected" );
		return -1;
	}
	else if ( size < 0 ) {	
		warning ( "Socket is broken!" );
		return -2;
	}

	if ( buf.size() ) buf.clear();
	buf.append ( data, size );
	return 0;
}



// Returns the Socket
const SOCKET& Socket::getSocket ( void ) {
	return  m_sock;
}

// Returns File the Socket
const SOCKET& Socket::getFileSocket ( void ) {
	return  m_sock_file;
}

// Set manually the Socket. BE CAREFUL, can break the sock!
// as well the socket get nonblocking
void Socket::setSocket ( SOCKET sock ) {
	m_sock = sock;
	fcntl ( m_sock, F_SETFL, fcntl ( getSocket(), F_GETFL, 0 ) | O_NONBLOCK );
}


// Set the IP

void Socket::setIp ( void ) {

	struct sockaddr_in addr;
	socklen_t len = sizeof ( addr );
	const char *rtn;

	getsockname ( m_sock, ( struct sockaddr*)&addr, &len );

	rtn = inet_ntoa(addr.sin_addr);
	m_ip = std::string ( rtn );

}


// return the Socket ip

std::string& Socket::getSocketIp ( void ) {
	return m_ip;
}

}
